package cn.xinfei.xdecision.data.core.util;

import cn.xinfei.xdecision.common.model.datax.consts.VariableConst;
import cn.xinfei.xdecision.common.model.datax.datainterface.v2.VarInterfaceInfo;
import cn.xinfei.xdecision.common.model.datax.datainterface.v2.VariableInterface;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import jodd.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

public class VarCacheUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(VarCacheUtils.class);

    public static List<Long> buildVirtualDataSourceFromCache(Optional<Map<Integer, VarInterfaceInfo>> varInterfaceDataCacheLoader, List<Long> httpDataSourceIdList) {
        List<Long> virtualHttpDataSourceIdList;
        virtualHttpDataSourceIdList = varInterfaceDataCacheLoader.get()
                .entrySet()
                .stream()
                .filter(Objects::nonNull)
                .filter(item -> httpDataSourceIdList.contains(Long.valueOf(item.getValue().getId())))
                .filter(item -> VariableConst.VIRTUAL_EXECUTOR_ENUMS.contains(item.getValue().getType())
                        && item.getValue().getStatus() == 1)
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))
                .keySet()
                .stream()
                .filter(Objects::nonNull)
                .map(Long::valueOf)
                .collect(Collectors.toList());
        return virtualHttpDataSourceIdList;
    }

    public static List<Long> buildHttpDataSourceFromCacheLoader(Set<String> varCodes, Optional<List<VariableInterface>> varInterfaceRelCacheLoader) {
        List<Long> httpDataSourceIdList;
        httpDataSourceIdList = varInterfaceRelCacheLoader.get()
                .stream()
                .filter(item -> varCodes.contains(item.getVariableCode()))
                .map(VariableInterface::getDatasourceId)
                .map(Long::valueOf)
                .collect(Collectors.toList());
        return httpDataSourceIdList;
    }

    public static Map<String, List<String>> getApiAndVarsFeeAttrDataSourcesFromCache(
            Collection<String> varCodes,
            List<Long> dataSourceList,
            Optional<List<VariableInterface>> varInterfaceRelCacheLoader) {

        if (CollectionUtils.isEmpty(dataSourceList)) {
            return Collections.emptyMap();
        }

        List<String> apiList = Optional.of(dataSourceList).orElse(Collections.emptyList())
                .stream().map(item -> varInterfaceRelCacheLoader.get()
                        .stream().filter(datasource -> datasource.getDatasourceId().equals(item.intValue()))
                        .collect(Collectors.toList()))
                .map(item -> item.stream()
                        .map(VariableInterface::getApi).collect(Collectors.toList()))
                .flatMap(Collection::stream)
                .distinct()
                .collect(Collectors.toList());

        Map<String, List<String>> apiAndVarMap = Maps.newHashMap();
        if (CollectionUtils.isEmpty(apiList)) {
            LOGGER.info("varCodes: {}, apiList is empty from cache", JSONObject.toJSONString(varCodes));
            return apiAndVarMap;
        }

        apiList.forEach(item -> {
            List<String> varCodeList = varInterfaceRelCacheLoader.get().stream().filter(datasource -> datasource.getApi().equals(item))
                    .collect(Collectors.toList())
                    .stream()
                    .filter(varInterface -> dataSourceList.contains(varInterface.getDatasourceId().longValue()))
                    .map(VariableInterface::getVariableCode)
                    .filter(varCodes::contains)
                    .filter(StringUtil::isNotBlank)
                    .collect(Collectors.toList());
            apiAndVarMap.put(item, varCodeList);
        });

        LOGGER.info("varCodes: {}, dataSourceList: {},apiList: {}",
                JSONObject.toJSONString(varCodes),
                JSONObject.toJSONString(dataSourceList),
                JSONObject.toJSONString(apiList));
        return apiAndVarMap;
    }
}
